package com.storyroad.utils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import com.storyroad.responseClasses.NotificationObject;

/**
 * This class handles the creation of the notifications and later verbalizing the notifications to display it to the user.
 * There are 5 actions that generates a notification: (1) when a user rates one of your story fragments, (2) when a user
 * posts a comment on your story fragment, (3) when a user starts following you, (4) when a user links a story fragment to a story
 * which contains a story fragment that you own and (5) when a user that you follow adds a new content.
 *
 */
public class CreateNotification {

	private Connection conn;
	private PreparedStatement stmt;
	private java.util.Date today;
	private Timestamp timeStamp;
	private ResultSet rs;
	// All possible notification types
	private static final byte RATE_N_TYPE = 1;
	private static final byte COMMENT_N_TYPE = 2;
	private static final byte FOLLOW_N_TYPE = 3;
	private static final byte LINK_N_TYPE = 4;
	private static final byte FOLLOWER_CONTENT_N_TYPE = 5;

	public CreateNotification() {
		conn = new DBConnection().connect();
		stmt = null;
		today = null;
		rs = null;
		timeStamp = null;
	}

	/**
	 * Creates a notification which is due to a rate action. Only the owner of the story fragment is notified after it
	 * is successfully rated.
	 * @param source_u_id ID of the user who rated the story
	 * @param target_s_id ID of the story fragment which is rated
	 */
	public void createRateNotification(int source_u_id, int target_s_id) {
		int u_id;
		String targetUserId = ",";
		try {
			stmt = conn.prepareStatement("SELECT owner FROM "
					+ TableNames.STORIES_TABLE + " WHERE s_id = ?");
			stmt.setInt(1, target_s_id);
			rs = stmt.executeQuery();
			if (rs.next()) {
				u_id = rs.getInt("owner");
				//targetUserId shows for which users a notification is generated
				targetUserId = targetUserId + u_id + ",";
				today = new java.util.Date();
				timeStamp = new Timestamp(today.getTime());
				stmt = conn.prepareStatement("INSERT INTO "	+ TableNames.NOTIFICATION_TABLE
								+ "(n_id,source_u_id,target_u_id,n_type,date,target_s_id) VALUES(?,?,?,?,?,?)");
				stmt.setNull(1, Types.INTEGER);
				stmt.setInt(2, source_u_id);
				stmt.setString(3, targetUserId);
				stmt.setByte(4, RATE_N_TYPE);
				stmt.setTimestamp(5, timeStamp);
				stmt.setInt(6, target_s_id);
				stmt.executeUpdate();
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Creates a notification which is due to a comment action. Only the owner of the fragment is notified after the comment
	 * is successfully posted.
	 * @param source_u_id ID of the user who posted the comment
	 * @param target_s_id ID of the story to which a comment is posted
	 */
	public void createCommentNotification(int source_u_id, int target_s_id) {
		int u_id;
		String targetUserId = ",";
		try {
			stmt = conn.prepareStatement("SELECT owner FROM "
					+ TableNames.STORIES_TABLE + " WHERE s_id = ?");
			stmt.setInt(1, target_s_id);
			rs = stmt.executeQuery();
			if (rs.next()) {
				u_id = rs.getInt("owner");
				//targetUserId shows for which users a notification is generated
				targetUserId = targetUserId + u_id + ",";
				today = new java.util.Date();
				timeStamp = new Timestamp(today.getTime());
	
				stmt = conn.prepareStatement("INSERT INTO "	+ TableNames.NOTIFICATION_TABLE
								+ "(n_id,source_u_id,target_u_id,n_type,date,target_s_id) VALUES(?,?,?,?,?,?)");
				stmt.setNull(1, Types.INTEGER);
				stmt.setInt(2, source_u_id);
				stmt.setString(3, targetUserId);
				stmt.setByte(4, COMMENT_N_TYPE);
				stmt.setTimestamp(5, timeStamp);
				stmt.setInt(6, target_s_id);
				stmt.executeUpdate();
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Creates a notification which is due to a follow action. User with ID = target_u_id is notified after
	 * the user with ID = source_u_id successfully starts following him.
	 * @param source_u_id ID of the user who started to follow the user with ID = target_u_id
	 * @param target_u_id ID of the user who is followed by the user with ID = source_u_id
	 */
	public void createFollowNotification(int source_u_id, int target_u_id) {
		String targetUserId = "," + target_u_id + ",";
		today = new java.util.Date();
		timeStamp = new Timestamp(today.getTime());
		try {
			stmt = conn.prepareStatement("INSERT INTO "	+ TableNames.NOTIFICATION_TABLE
							+ "(n_id,source_u_id,target_u_id,n_type,date) VALUES(?,?,?,?,?)");
			stmt.setNull(1, Types.INTEGER);
			stmt.setInt(2, source_u_id);
			stmt.setString(3, targetUserId);
			stmt.setByte(4, FOLLOW_N_TYPE);
			stmt.setTimestamp(5, timeStamp);
			stmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Creates notifications which are due to a link fragment action. All users who own a fragment in the story
	 * (to which a fragment is linked) are sent a notification.
	 * @param source_u_id ID of the user who linked the story fragment
	 * @param target_s_id ID of the story fragment to which another fragment is linked
	 */
	public void createLinkedStoryNotification(int source_u_id, int target_s_id) {
		int size;
		int s_id;
		String targetUserId = ",";
		GetStoryLinks links = new GetStoryLinks();
		// Gets the list of owners who own a fragment in this story fragment tree. Each of them will be sent a notification.
		links.getStoryLink(target_s_id);
		size = links.resultList.size();
		for (int i = 0; i < size; i++) {
			s_id = links.resultList.get(i).getStory_id();
			try {
				stmt = conn.prepareStatement("SELECT owner FROM "
						+ TableNames.STORIES_TABLE + " WHERE s_id = ?");
				stmt.setInt(1, s_id);
				rs = stmt.executeQuery();
				if (rs.next()) {
					// targetUserId contains all story fragment owners as stated above
					targetUserId = targetUserId + rs.getInt("owner") + ",";
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		today = new java.util.Date();
		timeStamp = new Timestamp(today.getTime());
		try {
			stmt = conn.prepareStatement("INSERT INTO "	+ TableNames.NOTIFICATION_TABLE
							+ "(n_id,source_u_id,target_u_id,n_type,date,target_s_id) VALUES(?,?,?,?,?,?)");
			stmt.setNull(1, Types.INTEGER);
			stmt.setInt(2, source_u_id);
			stmt.setString(3, targetUserId);
			stmt.setByte(4, LINK_N_TYPE);
			stmt.setTimestamp(5, timeStamp);
			stmt.setInt(6, target_s_id);
			stmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Creates notifications which are due to the followed user posting a new story fragment to the system. All users
	 * who follow this user (ID = source_u_id) are sent a notification.
	 * @param source_u_id ID of the user who posted a new story fragment
	 * @param target_s_id ID of the story fragment which is created by the user with ID = source_u_id
	 */
	public void createFollowerContentNotification(int source_u_id, int target_s_id) {
		String targetUserId = ",";
		try {
			stmt = conn.prepareStatement("SELECT follower_id FROM " + TableNames.FOLLOW_TABLE + " WHERE followed_id = ?");
			stmt.setInt(1, source_u_id);
			rs = stmt.executeQuery();
			while (rs.next()) {
				// All users who follow this user are going to receive a notification
				targetUserId = targetUserId + rs.getInt("follower_id") + ",";
			}
			if (targetUserId != "") {
				today = new java.util.Date();
				timeStamp = new Timestamp(today.getTime());
				stmt = conn.prepareStatement("INSERT INTO "	+ TableNames.NOTIFICATION_TABLE
								+ "(n_id,source_u_id,target_u_id,n_type,date,target_s_id) VALUES(?,?,?,?,?,?)");
				stmt.setNull(1, Types.INTEGER);
				stmt.setInt(2, source_u_id);
				stmt.setString(3, targetUserId);
				stmt.setByte(4, FOLLOWER_CONTENT_N_TYPE);
				stmt.setTimestamp(5, timeStamp);
				stmt.setInt(6, target_s_id);
				stmt.executeUpdate();
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Generates notification messages using the data in the Notification table in the DB.
	 * @param username name of the user who carried out the action
	 * @param n_type type of the notification which shows the action that generated this notification
	 * @param storyTitle name of the story fragment
	 * @param s_id ID of the story fragment which has been a part of the notification
	 * @param u_id ID of the user who carried out the action
	 * @param parentStoryTitle name of the story fragment to which another fragment is linked
	 * @return an instance of {@link com.storyroad.responseClasses.NotificationObject} which contains the notification message
	 */
	public static NotificationObject createNotificationObject(String username, byte n_type, String storyTitle, int s_id, int u_id, String parentStoryTitle) {

		int contentId;
		boolean isStory = true;
		String message = "";
		NotificationObject notification;

		switch (n_type) {
			case RATE_N_TYPE:
				message += username + " rated your story \"" + storyTitle + "\".";
				contentId = s_id;
				break;
			case COMMENT_N_TYPE:
				message += username + " commented on your story \"" + storyTitle + "\".";
				contentId = s_id;
				break;
			case FOLLOW_N_TYPE:
				message += username + " started following you.";
				contentId = u_id;
				isStory = false;
				break;
			case LINK_N_TYPE:
				message += username + " linked a new story fragment to \"" + parentStoryTitle + "\".";
				contentId = s_id;
				break;
			case FOLLOWER_CONTENT_N_TYPE:
				message += username + " created a new story fragment \"" + storyTitle + "\".";
				contentId = s_id;
				break;
			default:
				contentId = -1;
				break;
		}

		if (isStory) {
			notification = new NotificationObject(message, contentId, isStory);
		} else {
			notification = new NotificationObject(message, username, isStory);
		}
		return notification;
	}

}
